<?php

    $rootDir = $_SERVER['DOCUMENT_ROOT'];

    require_once($rootDir.'/classes/LeproBJAppSettings.class.php');

    class Card {
    
        public function __construct($cardId) {        
            $this->_cardId = $cardId;
        }
        
        public function getCardID() {
            return $this->_cardId;
        }
        
        public function getScore($aceIsOne=false, $use21rules=null, $jokerValue=null) {
            return self::getScoreById($this->_cardId, $aceIsOne, $use21rules, $jokerValue);
        }
        
        public function getImageURL() {
            return self::getCardImageURL($this->_cardId);
        }        
        
        public static function getScoreById($cardId, $aceIsOne=false, $use21rules=null, $jokerValue=null, $aceValue=null) {
            $use21rules = ($use21rules != null) ? $use21rules : LeproBJAppSettings::USE_21_RULES; 
            $jokerValue = ($jokerValue != null) ? $jokerValue : LeproBJAppSettings::JOKER_VALUE;
            // 10/A - 10, 11/B - J, 12/C - Q, 13/D - K, 14/E - A, 15/F - Joker
            $value = hexdec($cardId[0]);            
            if (($value < 6) && $use21rules) return 6;
            if (($value > 10) && ($value < 14)) return ($use21rules ? ($value - 9) : 10);
            if ($value == 14) return ($aceValue == null) ? ($aceIsOne ? 1 : 11) : $aceValue;
            if ($value == 15) return $jokerValue;
            return $value;
        }       
        
        public static function getCardIdByUserData($voice, $karma, $suit=null, $use21rules=null) {     
            $use21rules = ($use21rules != null) ? $use21rules : LeproBJAppSettings::USE_21_RULES;
            $suit = ($suit != null) ? $suit : LeproBJAppSettings::$CARDS_SUITS[rand(0, 3)];
            srand();
            $score = 0;       
            if (rand(0, 76) == 15) return "F".$suit; // joker              
            if ($use21rules) {           
                $kresult = floor(sqrt(abs($karma)) * 0.25);
                // $kresult = round(sqrt(abs($karma)) * 0.25);
                $score = 3 + abs($voice) + $kresult;
                if ($voice > 4) $score += (rand(1, 6) == 1) ? 1 : 0;
                if ($score < 6) $score = 6;
                // karma        result   voice
                //                       1  2   3   4   5   6   7
                // 0 : 15       0        6  6   6   7   8   9   10    
                // 16 : 63      1        6  6   7   8   9   10  J
                // 64 : 143     2        6  7   8   9   10  J   Q
                // 144 : 255    3        7  8   9   10  J   Q   K
                // 256 : 399    4        8  9   10  J   Q   K   A
                // 400 : 575    5        9  10  J   Q   K   A   A
                // 576 : 783    6        10 J   Q   K   A   A   A
                // 784 : 1023   7        J  Q   K   A   A   A   A
                // 1024 : 1295  8        Q  K   A   A   A   A   A
                // 1296 : 1599  9        K  A   A   A   A   A   A                
            } else {
                $kresult = floor(sqrt(abs($karma)) / 3);
                // $kresult = round(sqrt(abs($karma)) / 3);                
                $score = 1 + abs($voice) + $kresult;    
                if ($voice > 3) $score += ((($kresult >= 5) ? 1 : 0) + ((rand(1, 5) == 1) ? 1 : 0));            
                if ($score < 2) $score = 2;
                // karma        kresult   voice
                //                       1  2   3   4   5   6   7
                // 0 : 8        0        2  3   4   5   6   7   8    
                // 9 : 35       1        3  4   5   6   7   8   9
                // 36 : 80      2        4  5   6   7   8   9   10
                // 81 : 143     3        5  6   7   8   9   10  J
                // 144 : 224    4        6  7   8   9   10  J   Q
                // 225 : 323    5        7  8   9   J   Q   K   A
                // 324 : 439    6        8  9   10  Q   K   A   A
                // 440 : 574    7        9  10  J   K   A   A   A
                // 575 : 728    8        10 J   Q   A   A   A   A
                // 729 : 899    9        J  Q   K   A   A   A   A
                // 900 : 1088  10        Q  K   A   A   A   A   A
                // 1089 : 1268 11        K  A   A   A   A   A   A
            }
            if ($score > 14) $score = 14;            
            return (dechex($score).$suit);
        }
        
        public static function getCardName($cardId) {            
            $value = intval(hexdec($cardId[0]));
            $suit = $cardId[1];
            $joiner = (LeproBJAppSettings::$CARDS_NAMES_JOIN_PREP != null) ? ' '.LeproBJAppSettings::$CARDS_NAMES_JOIN_PREP.' ' : ' ';
            return ($value < 15) ? 
                        (LeproBJAppSettings::$CARDS_NAMES[($value - 2)].$joiner.
                        LeproBJAppSettings::$CARDS_SUITS_NAMES[self::getSuitId($suit)])
                      : (LeproBJAppSettings::$SUITS_COLORS_NAMES[self::isBlackSuit($suit) ? 1 : 0].' '.
                        LeproBJAppSettings::$CARDS_NAMES[($value - 2)]); 
        }
        
        private static function getSuitId($suitChar) {
            return array_search(strtolower($suitChar), LeproBJAppSettings::$CARDS_SUITS);
        }
        
        private static function isBlackSuit($suitChar) {
            return in_array($suitChar, LeproBJAppSettings::$BLACK_SUITS);
        }
        
        public static function getCardColor($cardId) {
        	// true - card is red, false - card is black
        	return !self::isBlackSuit($cardId[1]);
        }
        
        public static function getCardHTMLCode($cardId, $useCodes=null, $useUTFSuits=false) {
            $useCodes = ($useCodes != null) ? $useCodes : LeproBJAppSettings::USE_HTML_ENTS;
            $value = intval(hexdec($cardId[0]));            
            return ($useCodes ? (
                        (($value > 9) ? LeproBJAppSettings::$CARDS_HTML_CODES[($value - 10)] : $value)  
                   ) : (
                        (($value > 10) ? LeproBJAppSettings::$CARDS_CODES[($value - 11)] : $value) 
                   )).(($value < 15) 
                        ? ($useUTFSuits 
                            ? LeproBJAppSettings::$CARDS_SUITS_UTF_ENTS[self::getSuitId($cardId[1])] 
                            : LeproBJAppSettings::$CARDS_SUITS_HTML_ENTS[self::getSuitId($cardId[1])]
                        ) : ($useUTFSuits 
                            ? LeproBJAppSettings::$CARDS_COLORS_UTF_ENTS[self::isBlackSuit($cardId[1]) ? 1 : 0] 
                            : LeproBJAppSettings::$CARDS_COLORS_HTML_ENTS[self::isBlackSuit($cardId[1]) ? 1 : 0]
                        ));
        }
        
        public static function getCardImageFName($cardId) {
            return self::getCardNameForFile($cardId).'.'.LeproBJAppSettings::$CARDS_FNAME_EXT;
        }   
        
        private static function getCardNameForFile($cardId) {
            $value = intval(hexdec($cardId[0]));
            $suit = $cardId[1];
            $fname = LeproBJAppSettings::$CARDS_BACK_FNAME;
            if ($value < 15) { // not joker
                $fname = ($value > 10 ? LeproBJAppSettings::$CARDS_NUMS_TO_FNAMES[$value] : $value).
                         LeproBJAppSettings::$CARDS_FNAME_DELIM.
                         LeproBJAppSettings::$CARDS_SUITS_TO_FNAMES[$suit];
            } else {
                $fname = LeproBJAppSettings::$CARDS_JOKER_SUIT_TO_FNAME[$suit].
                         LeproBJAppSettings::$CARDS_FNAME_DELIM.
                         LeproBJAppSettings::$CARDS_NUMS_TO_FNAMES[$value];
            }            
            return $fname;
        }
        
        public static function getCardSummary($cardId, $use21rules=null, $fnameWithExt=true) {
            $use21rules = ($use21rules != null) ? $use21rules : LeproBJAppSettings::USE_21_RULES;
            return array(
                'id' => $cardId,
                'file' => ($fnameWithExt ? self::getCardImageFName($cardId) : self::getCardNameForFile($cardId)),
                'name' => self::getCardName($cardId),
                'html' => self::getCardHTMLCode($cardId),
                'score' => self::getScoreById($cardId, null, null, '2 | ?', '1 | 11')
            );
        }  
        
        public static function getCardsScores($cardsIdsList) { // TODO: make private
            if (count($cardsIdsList) == 0) return 0;
            $sum = 0;
            $aces = array();
            $jokers = array();
            $suits = array();
            $cards = array();
            $scores = array();
            foreach (LeproBJAppSettings::$CARDS_SUITS as $suit) {
                $suits[$suit] = 0; 
            }
            $i = 0;
            foreach ($cardsIdsList as $cardId) {
                $value = hexdec($cardId[0]);
                $suit = $cardId[1];            
                $isAce = ($value == 14); 
                $isJoker = ($value == 15); 
                if (!$isAce && !$isJoker) {
                    $scores[$i] = self::getScoreById($cardId);
                    $sum += $scores[$i];
                    $suits[$suit] += 1;                    
                } else {
                    if ($isAce) $aces[$i] = $suit;
                    if ($isJoker) $jokers[$i] = $suit; 
                }
                $cards[$i] = $cardId;
                $i++;
            }
            foreach ($aces as $cardIdx => $aceSuit) {
                $scores[$cardIdx] = ($sum <= 10) ? 11 : 1; // TODO: getScoreById($aceId, ($sum > 10));
                $sum += $scores[$cardIdx]; 
                $suits[$aceSuit] += 1;                 
            }
            foreach ($jokers as $cardIdx => $jokerSuit) { 
                // $isBlack = self::isBlackSuit($jokerSuit); // TODO: place this, recheck
                $isBlack = in_array($jokerSuit, LeproBJAppSettings::$BLACK_SUITS);
                $pairedSuits = $isBlack ? LeproBJAppSettings::$BLACK_SUITS : LeproBJAppSettings::$RED_SUITS;
                $justPaired = true;
                //var_dump($suits);
                foreach($suits as $suit => $num) {
                    //echo $suit.'.'.$num.'.'.$pairedSuits.'.'.$justPaired.';';
                    if (($num > 0) && (!in_array($suit, $pairedSuits))) $justPaired = false; 
                }
                $scores[$cardIdx] = ($justPaired && ($sum <= 21) && ($sum >= 6)) ? (21 - $sum) : 2; // TODO: getScoreById($aceId, null, null, 2); 
                $sum += $scores[$cardIdx];
            }        
            ksort($cards, SORT_NUMERIC);
            ksort($scores, SORT_NUMERIC);
            return array(
                    "sum" => $sum,
                    "cards" => $cards,
                    "scores" => $scores
                );
        }   
        
        public static function getCardsScoreSum($cardsIdsList) {
            $summary = Card::getCardsScores($cardsIdsList);             
            return $summary["sum"];
        }
        
        public static function getCardsScoreSumSummary($usersToCardIdsList) {
            $cardsSummary = Card::getCardsScores(array_values($usersToCardIdsList));
            $cardsSummary["scores"] = array_combine(array_keys($usersToCardIdsList), $cardsSummary["scores"]);
            return $cardsSummary;
        }    
        
        /* public static function getCardsScoreSum($cardsIdsList) {
            if (count($cardsIdsList) == 0) return 0;
            $sum = 0;
            $aces = array();
            $jokers = array();
            $suits = array();
            foreach (LeproBJAppSettings::$CARDS_SUITS as $suit) {
                $suits[$suit] = 0; 
            }
            foreach ($cardsIdsList as $cardId) {
                $value = hexdec($cardId[0]);
                $suit = $cardId[1];            
                $isAce = ($value == 14); 
                $isJoker = ($value == 15); 
                if (!$isAce && !$isJoker) {
                    $sum += self::getScoreById($cardId);
                    $suits[$suit] += 1;                    
                } else {
                    if ($isAce) $aces[] = $suit;
                    if ($isJoker) $jokers[] = $suit; 
                }
            }
            foreach ($aces as $aceSuit) {
                $sum += ($sum <= 10) ? 11 : 1; // getScoreById($aceId, ($sum > 10));
                $suits[$aceSuit] += 1;                 
            }
            foreach ($jokers as $jokerSuit) { 
                // $isBlack = self::isBlackSuit($jokerSuit); // TODO: place this, recheck
                $isBlack = in_array($jokerSuit, LeproBJAppSettings::$BLACK_SUITS);
                $pairedSuits = $isBlack ? LeproBJAppSettings::$BLACK_SUITS : LeproBJAppSettings::$RED_SUITS;
                $justPaired = true;
                //var_dump($suits);
                foreach($suits as $suit => $num) {
                    //echo $suit.'.'.$num.'.'.$pairedSuits.'.'.$justPaired.';';
                    if (($num > 0) && (!in_array($suit, $pairedSuits))) $justPaired = false; 
                }
                $sum += ($justPaired && ($sum <= 21) && ($sum >= 6)) ? (21 - $sum) : 2; // getScoreById($aceId, null, null, 2);
            }
            return $sum;
        } */    
        
    }

?>
